package com.fcat.base.smartapi.lib;

import com.fcat.base.smartapi.service.impl.TokenServiceImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.crypto.Cipher;
import java.security.Key;

public class MeterKeys {
    private static final Logger LOGGER = LoggerFactory.getLogger(TokenServiceImpl.class);

    private String VendingKey = "abababababababab";
    private final String IIN = "600727";
    private String DRN = "00000000000";        // Meter No. 11/13 digits,
    private String KT = "2";              // Key Type
    private String SGC = "123456";
    private String KRN = "1";
    private String TI = "01";              // TariffIndex  00~99
    private byte[] Meter_Key = new byte[8];

    public MeterKeys() {
    }

    public MeterKeys(String meterNo) {
        setDRN(meterNo);
    }

    public MeterKeys(String meterNo, String vendingKey) {
        setDRN(meterNo);
        setVendingKey(vendingKey);
    }

    public byte[] getMeterKey() {
        return Meter_Key;
    }
    public String getMeterKeyString() {
        StringBuilder mks = new StringBuilder();
        for (byte mk: Meter_Key) {
            mks.append(String.format("%02X", mk));
        }
        return mks.toString();
    }

    public String getVendingKey() {
        return VendingKey;
    }

    public void setVendingKey(String vendingKey) {
        VendingKey = vendingKey;
    }

    public String getDRN() {
        return DRN;
    }

    public void setDRN(String DRN) {
        if ((DRN.length() == 11) || (DRN.length() == 13)) {
            this.DRN = DRN;
        }
    }

    public String getKT() {
        return KT;
    }

    public void setKT(String KT) {
        if ((KT.equals("0")) || (KT.equals("1")) || (KT.equals("2")) || (KT.equals("3"))) {
            this.KT = KT;
        }
    }

    public String getSGC() {
        return SGC;
    }

    public void setSGC(String SGC) {
        this.SGC = SGC;
    }

    public String getKRN() {
        return KRN;
    }

    public void setKRN(String KRN) {
        int krn = Integer.valueOf(KRN);
        if ((krn >= 1) && (krn <= 9)) {
            this.KRN = KRN;
        }
//        String krn0 = "0" + KRN;
//        this.KRN = KRN.substring(KRN.length() - 1);
    }

    public String getTI() {
        return TI;
    }

    public void setTI(String TI) {
        int ti = Integer.getInteger(TI);
        if ((ti >= 1) && ( ti <= 99) && (TI.length() == 2)) {
            this.TI = TI;
        }
    }

    public void setTI(int ti) {
        if ((ti >= 1) && ( ti <= 99)) {
            this.TI = String.format("%02d", ti);
        }
    }

    private Key getKey(byte[] arrBTmp) throws Exception {
        // 创建一个空的8位字节数组（默认值为0）
        byte[] arrB = new byte[8];

        // 将原始字节数组转换为8位
        for (int i = 0; i < arrBTmp.length && i < arrB.length; i++) {
            arrB[i] = arrBTmp[i];
        }

        // 生成密钥
        Key key = new javax.crypto.spec.SecretKeySpec(arrB, "DES");

        return key;
    }

    private String getPANBlock() {
        StringBuilder pb = new StringBuilder();
        int drnLen = DRN.length();
        switch (drnLen) {
            case 11:
                pb.append(IIN.substring(IIN.length() - 5));
                pb.append(DRN);
                break;

            case 13:
                pb.append(IIN.substring(IIN.length() - 3));
                pb.append(DRN);
                break;

            default:
        }
        return pb.toString();
    }

    private String getCONTROLBlock() {
//        Position 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
//        Value    C  S  S  S  S  S  S  T  T  R  F  F  F  F  F  F
        // C - KT; S - SGC; T - TI; R - KRN;
        String cb = KT + SGC + TI + KRN + "FFFFFF";
        return cb;
    }

    private static byte[] hexStr2Bytes(String hexStr) {
        String tmpStr = hexStr;
        int len = hexStr.length();
        if ((len % 2) != 0) {
            tmpStr = "0" + tmpStr;
            len = tmpStr.length();
        }
        byte[] data = new byte[len / 2];
        for (int i = 0; i < data.length; i++) {
            String tmp = tmpStr.substring(i * 2, i * 2 + 2);
            data[i] = (byte) Integer.parseInt(tmp, 16);
        }
        return data;
    }

    private byte[] getDataBlock(String panBlock, String controlBlock) {
        byte[] db = new byte[8];
        byte[] pb = hexStr2Bytes(panBlock);
        byte[] cb = hexStr2Bytes(controlBlock);
        if ((pb.length == 8) && (cb.length == 8)) {
            for (int i = 0; i < 8; i++) {
                db[i] = (byte) (pb[i] ^ cb[i]);
            }
        } else {
            LOGGER.error("PANBlock or CONTROLBlock error!");;
        }

        return db;
    }

    public void DKGA2() throws Exception {
        byte[] dataBlock = getDataBlock(getPANBlock(), getCONTROLBlock());

        Cipher mEncryptCipher = null;
        mEncryptCipher = Cipher.getInstance("DES/ECB/NoPadding");
        Key key = getKey(hexStr2Bytes(VendingKey));
        mEncryptCipher.init(Cipher.ENCRYPT_MODE, key);
        Meter_Key = mEncryptCipher.doFinal(dataBlock);

        byte[] kb = key.getEncoded();
        for (int i = 0; i < Meter_Key.length; i++) {
            Meter_Key[i] = (byte) (Meter_Key[i] ^ dataBlock[i] ^ kb[i]);
        }
    }
}
